/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.quangtin3.reverse;

import com.quangtin3.Bouncing;
import com.quangtin3.Utils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.Socket;
import org.apache.log4j.Logger;

/**
 * Side B of reversal relay.
 * @author quangtin3@gmai.com
 */
public class SideB implements Runnable {

    private int transPort = 3105,  bncToPort = 8583;
    private String serverTrans = "127.0.0.1";
    private String toServerBnc = "192.168.0.163";
    static String REQUEST_CONNECT = "connect to 127.0.0.1:8585";
    static String RESPONSE_CONNECT_OK = "connect to 127.0.0.1:8585 ok";
    static String RESPONSE_CONNECT_FAIL = "connect to 127.0.0.1:8585 fail";
    private Logger log;

    public static void main(String[] args) {
        new SideB(Logger.getLogger("sideB"));
    }

    public SideB(Logger log) {
        this.log = log;
        Thread t = new Thread(this, "SideB");
        t.start();
    }

    public void run() {
        log.info("system start");

        int i_trans = 0;
        while (true) {
            i_trans++;

            Socket sock_b = null;
            Writer out = null;
            BufferedReader in = null;
            int retry_count = 0;

            while (sock_b == null) {
                retry_count++;

                try {
                    log.info(retry_count + " connect to trans (" + serverTrans + ":" + transPort + ")...");
                    sock_b = new Socket(serverTrans, transPort);

                    out = new OutputStreamWriter(sock_b.getOutputStream(), "8859_1");
                    in = new BufferedReader(
                            new InputStreamReader(sock_b.getInputStream(), "8859_1"));
                } catch (IOException e) {
                    if (retry_count > 100) {
                        log.info("cannot connect to trans, system exit");
                        System.exit(-1);
                    }
                    log.info(retry_count + " connect to trans error. sleep 5s before retry");
                    sock_b = null;
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException ie) {
                    }
                }
            }

            log.info("connected " + transPort);

            boolean oneMoreBncSuccess = false;
            int i_relay = 0;

            while (!oneMoreBncSuccess) {
                i_relay++;
                log.info(i_relay + " receiving request...");

                char[] cbuff = new char[256];
                int len = 0;

                try {
                    len = in.read(cbuff);
                } catch (IOException e) {
                    log.info("connect to server error. close this and retry");
                    try {
                        sock_b.close();
                    } catch (IOException ioe) {
                    }
                    break;
                }

                //compare
                String result = Utils.getString(cbuff, len);
                log.info(i_relay + " received request " + result);

                if (result.equalsIgnoreCase(REQUEST_CONNECT)) {
                    //if (true) {
                    log.info("connect for request");

                    try {
                        Socket sock_bnc = new Socket(toServerBnc, bncToPort);
                        log.info("connected to " + toServerBnc + ":" + bncToPort);

                        out.write(RESPONSE_CONNECT_OK);
                        out.flush();

                        log.info("response to trans server: " + RESPONSE_CONNECT_OK);

                        new Bouncing(sock_bnc, sock_b, log);
                        new Bouncing(sock_b, sock_bnc, log);
                        log.info("bouncing threads started.");
                        oneMoreBncSuccess = true;

                    } catch (IOException e) {
                        log.info("connect for request fail");
                        try {
                            sock_b.getOutputStream().write(RESPONSE_CONNECT_FAIL.getBytes());
                        } catch (IOException ioe) {
                            log.info("cannot reponse to server, close this connection and retry");
                            break;
                        }
                        oneMoreBncSuccess = false;
                    }

                } else {
                    log.info("unreconize, " + result + ". close and retry");
                    try {
                        sock_b.close();
                    } catch (IOException ioe) {
                    }
                    break;
                }
            }
        }
    }
}



